<?php
/**
 *
 *
 * This file is part of Webappkit, a packages system for PHP web apps
 * @link http://webappkit.net
 * @package dj
 * @subpackage forms
 * @author J.Ducastel <nospam0@ducastel.name>
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 */

/**
 * @property array $errors field => error message
 * @property array $cleaned_data fields validated, typed and cleaned
 * @property string $prefix prefix for id attributes
 */
class DjForm {

    /**
     * @param array $data bound data to validate
     */
    public function __construct($data=null) {
        if (is_array($data)) { // bound
            $this->data = $data;
            foreach ($this->_getFields() as $key => $field) {
                if (isset($data[$key]))
                    $field->bound($key, $data[$key]);
                else
                    $field->bound($key);
            }
        } else { // unbound
            // setting fields name
            foreach ($this->_getFields() as $key => $field) {
                $field->name = $key;
            }
        }
    }

    /**
     * @return bool
     */
    public function isBound() {
        return is_array($this->data);
    }

    /**
     * @return bool True if all fields are valid
     */
    public function isValid() {
        // unbound forms cannot be valid
        if (!$this->isBound())
            return false;
        // to store cleaned data
        $cleaned = array();
        // looping through fields
        foreach ($this->_getFields() as $key => $field) {
            // validating and storing cleaned data and errors
            try {
                $value = isset($this->data[$key])?$this->data[$key]:null;
                $cleaned[$key] = $field->clean($value);
            } catch (DjValidationError $e) {
                // return false;
                $this->errors[$key] = $e->getMessage();
            }
        }
        if (count($this->errors)==0) {
            // is valid
            $this->cleaned_data = $cleaned;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @return string HTML, a <p> for each field
     */
    public function asP() {
        $html = '';
        foreach ($this->_getFields() as $name => $field) {
            $html.='<p>'
            .'<label for="id_'.$name.'">'.$field->label.'</label>'
            .$field->__toString()
            .$field->error
            .'</p>';
        }
        return $html;
    }

    /**
     * @return bool True if contain file fields
     */
    public function isMultipart() {

    }

    /**
     * accessor for fields, bounds them to data if necessary
     *
     * /
    public function __get($field_name) {
        if (!property_exists($this, $field_name)
        or !is_a($this->$field_name, 'DjField')) {
            throw new DjNameError("no field $field_name");
            return false;
        }
        $field = $this->$field_name;
        if ($this->isBound()) {
            $field->bound($field_name, $this->data[$field_name]);
        } else {
            $field->bound($field_name);
        }
        return $field;
    }/**/

    public $errors = array();

    public $cleaned_data = array();

    public $prefix = '';

    protected $data;

    /**
     * @return array of DjField
     */
    protected function & _getFields() {
        $list = array();
        foreach ($this as $key => $field) {
            if (is_a($field, 'DjField'))
                $list[$key] = $field;
        }
        return $list;
    }
}